/*
 *  Copyright (C) 2022  贺龙宇
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include"SelectDev.h"

SelectDev::SelectDev(){}
SelectDev::~SelectDev(){}

bool SelectDev::OpenDevice(SerialPort &serial_port,int test_mode)
{
#ifdef NUC
    if(!TestSerial("/dev/ttyUSB0",test_mode))
#else
    if(!TestSerial("/dev/ttyS0",test_mode))
#endif
    {
        if(!TestSerial("/dev/ttyTHS2",test_mode))
        {
        printf("Open %d failed, device no found\n",test_mode);
        FYTLog->writeLog("Open "+std::to_string(test_mode)+" Failed",LOG_SELECT);
        return false;
        }
        else
        {
            serial_port.SetPortName("/dev/ttyTHS2");
            if(!serial_port.Init())
            {
                FYTLog->writeLog("In Function OpenDevice: /dev/ttyTHS2 init failed",LOG_SELECT);
                return false;
            }
            FYTLog->writeLog("Port " +std::to_string(test_mode) +" open success",LOG_SELECT);
            return true;
        }
    }
    else
    {
#ifdef NUC
        serial_port.SetPortName("/dev/ttyUSB0");
#else
        serial_port.SetPortName("/dev/ttyS0");
#endif
        if(!serial_port.Init()){
            FYTLog->writeLog("In Function OpenDevice: /dev/ttyS0 init failed",LOG_SELECT);
            return false;
        }
        FYTLog->writeLog("Port " +std::to_string(test_mode) +" open success",LOG_SELECT);
        return true;
    }
}

bool SelectDev::TestSerial(const char* port_name,int test_mode)
{
    SerialPort serial_port(port_name);
    if(serial_port.Init()==false)
    {
        return false;
    }
    if(test_mode==SELECTDEV_TFLUNA)
    {
        bool IsSuccess=IsTFLUNA(serial_port);
        serial_port.Destory();
        return IsSuccess;
    }
    if(test_mode==SELECTDEV_MCU)
    {
        bool IsSuccess=IsMcu(serial_port);
        serial_port.Destory();
        return IsSuccess;
    }
    return false;
}

bool SelectDev::IsTFLUNA(SerialPort &serial_port)
{
    
    uint8_t buffer[6];
    memset(buffer,0,sizeof(buffer));
    int start_clock = std::clock();
    int cnt=0;
    bool init=false;
    // printf("1\n");
    while((int)std::clock()-start_clock<1e6)
    {

    
        serial_port.Read(buffer,1);
        //  printf("1\n");
        if(buffer[0]!=0x59)      
	    {  
            continue;
        }

        serial_port.Read(buffer+1,1);
        if(buffer[1]!=0x59)
        {
            continue;
        }
        cnt++;
     
     
       
    }

    printf("TFLuna: Recieve %d data in one seconds\n",cnt);
    if(!cnt)
    {
        return false;
    }

    return true;
}

bool SelectDev::IsMcu(SerialPort &serial_port)
{
    uint8_t buffer[6];
    uint8_t buffer_send[6]={0x03,0xFC,0x00,0x00,0xFC,0x03};
    memset(buffer,0,sizeof(buffer));
    int start_clock = std::clock();
    int cnt=0;

    while((int)std::clock()-start_clock<2e6)
    {
     
        serial_port.Write(buffer_send,sizeof(buffer_send));
        /*兵种ID一直是0，说明没有收到数据，继续执行*/
        /*若不为0，则说明收到来自下位机的数据，结束握手*/
        if(buffer_send[2]!=0){
            FYTLog->writeLog("Recieve hold-hand data:"
               +std::to_string(int(hand_data.id))+" "+std::to_string(int(hand_data.enemy_color)),LOG_SELECT);
            // int T=100;
            /*接收成功，发送100次接收成功的数据给下位机进行标识*/
            // while(T--) serial_port.Write(buffer_send,sizeof(buffer_send));
            return true;
        }
    //  usleep(1);
        serial_port.Read(buffer,1);
     
        if(buffer[0]!=0x03)      
	    {  
            continue;
        }
     
        serial_port.Read(buffer+1,1);
        if(buffer[1]!=0xFC)
        {
            continue;
        }

        serial_port.Read(buffer+2,4);
        memcpy(buffer_send,buffer,sizeof(buffer_send));
        memcpy(&hand_data,buffer+2,sizeof(hand_data));
        cnt++; 
    }

    printf("MCU: Recieve %d data in one seconds\n",cnt);
    if(!cnt)
    {
        return false;
    }
    // printf("Recieve hold-hand data: %d %d \n",hand_data.id,hand_data.enemy_color);
    
    return true;
}

SelectDev *selectDev=new SelectDev;
